home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / vid_svgalib.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  21KB  |  1,004 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include <termios.h>
  21. #include <sys/ioctl.h>
  22. #include <sys/stat.h>
  23. #include <sys/vt.h>
  24. #include <stdarg.h>
  25. #include <stdio.h>
  26. #include <signal.h>
  27.  
  28. #include <asm/io.h>
  29.  
  30. #include "vga.h"
  31. #include "vgakeyboard.h"
  32. #include "vgamouse.h"
  33.  
  34. #include "quakedef.h"
  35. #include "d_local.h"
  36.  
  37. #define stringify(m) { #m, m }
  38.  
  39. unsigned short       d_8to16table[256];
  40. static byte        *vid_surfcache;
  41. static int        VID_highhunkmark;
  42.  
  43. int num_modes;
  44. vga_modeinfo *modes;
  45. int current_mode;
  46.  
  47. int num_shades=32;
  48.  
  49. struct
  50. {
  51.     char *name;
  52.     int num;
  53. } mice[] =
  54. {
  55.     stringify(MOUSE_MICROSOFT),
  56.     stringify(MOUSE_MOUSESYSTEMS),
  57.     stringify(MOUSE_MMSERIES),
  58.     stringify(MOUSE_LOGITECH),
  59.     stringify(MOUSE_BUSMOUSE),
  60.     stringify(MOUSE_PS2),
  61. };
  62.  
  63. static unsigned char scantokey[128];
  64. static byte vid_current_palette[768];
  65.  
  66. int num_mice = sizeof (mice) / sizeof(mice[0]);
  67.  
  68. int    d_con_indirect = 0;
  69.  
  70. int        svgalib_inited=0;
  71. int        UseMouse = 1;
  72. int        UseDisplay = 1;
  73. int        UseKeyboard = 1;
  74.  
  75. int        mouserate = MOUSE_DEFAULTSAMPLERATE;
  76.  
  77. cvar_t        vid_mode = {"vid_mode","5",false};
  78. cvar_t        vid_redrawfull = {"vid_redrawfull","0",false};
  79. cvar_t        vid_waitforrefresh = {"vid_waitforrefresh","0",true};
  80.  
  81. char    *framebuffer_ptr;
  82.  
  83. cvar_t  mouse_button_commands[3] =
  84. {
  85.     {"mouse1","+attack"},
  86.     {"mouse2","+strafe"},
  87.     {"mouse3","+forward"},
  88. };
  89.  
  90. int     mouse_buttons;
  91. int     mouse_buttonstate;
  92. int     mouse_oldbuttonstate;
  93. float   mouse_x, mouse_y;
  94. float    old_mouse_x, old_mouse_y;
  95. int        mx, my;
  96.  
  97. cvar_t    m_filter = {"m_filter","0"};
  98.  
  99. static byte     backingbuf[48*24];
  100.  
  101. int        VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
  102. byte    *VGA_pagebase;
  103.  
  104. void VGA_UpdatePlanarScreen (void *srcbuffer);
  105.  
  106. void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
  107. {
  108.     int i, j, k, plane, reps, repshift, offset, vidpage, off;
  109.  
  110.     if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
  111.  
  112.     if (vid.aspect > 1.5)
  113.     {
  114.         reps = 2;
  115.         repshift = 1;
  116.     } else {
  117.         reps = 1;
  118.         repshift = 0;
  119.     }
  120.  
  121.     vidpage = 0;
  122.     vga_setpage(0);
  123.  
  124.     if (VGA_planar)
  125.     {
  126.         for (plane=0 ; plane<4 ; plane++)
  127.         {
  128.         // select the correct plane for reading and writing
  129.             outb(0x02, 0x3C4);
  130.             outb(1 << plane, 0x3C5);
  131.             outb(4, 0x3CE);
  132.             outb(plane, 0x3CF);
  133.  
  134.             for (i=0 ; i<(height << repshift) ; i += reps)
  135.             {
  136.                 for (k=0 ; k<reps ; k++)
  137.                 {
  138.                     for (j=0 ; j<(width >> 2) ; j++)
  139.                     {
  140.                         backingbuf[(i + k) * 24 + (j << 2) + plane] =
  141.                                 vid.direct[(y + i + k) * VGA_rowbytes +
  142.                                 (x >> 2) + j];
  143.                         vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
  144.                                 pbitmap[(i >> repshift) * 24 +
  145.                                 (j << 2) + plane];
  146.                     }
  147.                 }
  148.             }
  149.         }
  150.     } else {
  151.         for (i=0 ; i<(height << repshift) ; i += reps)
  152.         {
  153.             for (j=0 ; j<reps ; j++)
  154.             {
  155.                 offset = x + ((y << repshift) + i + j) * vid.rowbytes;
  156.                 off = offset % 0x10000;
  157.                 if ((offset / 0x10000) != vidpage) {
  158.                     vidpage=offset / 0x10000;
  159.                     vga_setpage(vidpage);
  160.                 }
  161.                 memcpy (&backingbuf[(i + j) * 24],
  162.                         vid.direct + off, width);
  163.                 memcpy (vid.direct + off,
  164.                         &pbitmap[(i >> repshift)*width], width);
  165.             }
  166.         }
  167.     }
  168. }
  169.  
  170. void D_EndDirectRect (int x, int y, int width, int height)
  171. {
  172.     int i, j, k, plane, reps, repshift, offset, vidpage, off;
  173.  
  174.     if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return;
  175.  
  176.     if (vid.aspect > 1.5)
  177.     {
  178.         reps = 2;
  179.         repshift = 1;
  180.     } else {
  181.         reps = 1;
  182.         repshift = 0;
  183.     }
  184.  
  185.     vidpage = 0;
  186.     vga_setpage(0);
  187.  
  188.     if (VGA_planar)
  189.     {
  190.         for (plane=0 ; plane<4 ; plane++)
  191.         {
  192.         // select the correct plane for writing
  193.             outb(2, 0x3C4);
  194.             outb(1 << plane, 0x3C5);
  195.             outb(4, 0x3CE);
  196.             outb(plane, 0x3CF);
  197.  
  198.             for (i=0 ; i<(height << repshift) ; i += reps)
  199.             {
  200.                 for (k=0 ; k<reps ; k++)
  201.                 {
  202.                     for (j=0 ; j<(width >> 2) ; j++)
  203.                     {
  204.                         vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
  205.                                 backingbuf[(i + k) * 24 + (j << 2) + plane];
  206.                     }
  207.                 }
  208.             }
  209.         }
  210.     } else {
  211.         for (i=0 ; i<(height << repshift) ; i += reps)
  212.         {
  213.             for (j=0 ; j<reps ; j++)
  214.             {
  215.                 offset = x + ((y << repshift) + i + j) * vid.rowbytes;
  216.                 off = offset % 0x10000;
  217.                 if ((offset / 0x10000) != vidpage) {
  218.                     vidpage=offset / 0x10000;
  219.                     vga_setpage(vidpage);
  220.                 }
  221.                 memcpy (vid.direct + off, 
  222.                         &backingbuf[(i +j)*24],
  223.                         width);
  224.             }
  225.         }
  226.     }
  227. }
  228.  
  229. /*
  230. =================
  231. VID_Gamma_f
  232.  
  233. Keybinding command
  234. =================
  235. */
  236. void VID_Gamma_f (void)
  237. {
  238.     float    gamma, f, inf;
  239.     unsigned char    palette[768];
  240.     int        i;
  241.  
  242.     if (Cmd_Argc () == 2)
  243.     {
  244.         gamma = Q_atof (Cmd_Argv(1));
  245.  
  246.         for (i=0 ; i<768 ; i++)
  247.         {
  248.             f = pow ( (host_basepal[i]+1)/256.0 , gamma );
  249.             inf = f*255 + 0.5;
  250.             if (inf < 0)
  251.                 inf = 0;
  252.             if (inf > 255)
  253.                 inf = 255;
  254.             palette[i] = inf;
  255.         }
  256.  
  257.         VID_SetPalette (palette);
  258.  
  259.         vid.recalc_refdef = 1;                // force a surface cache flush
  260.     }
  261. }
  262.  
  263. void VID_DescribeMode_f (void)
  264. {
  265.     int modenum;
  266.     
  267.     modenum = Q_atoi (Cmd_Argv(1));
  268.     if ((modenum >= num_modes) || (modenum < 0 ) || !modes[modenum].width)
  269.         Con_Printf("Invalid video mode: %d!\n",modenum);
  270.     Con_Printf("%d: %d x %d - ",modenum,modes[modenum].width,modes[modenum].height);
  271.     if (modes[modenum].bytesperpixel == 0)
  272.         Con_Printf("ModeX\n");
  273.     else
  274.         Con_Printf("%d bpp\n", modes[modenum].bytesperpixel<<3);
  275. }
  276.  
  277. void VID_DescribeModes_f (void)
  278. {
  279.     int i;
  280.     
  281.     for (i=0;i<num_modes;i++)
  282.         if (modes[i].width) {
  283.             Con_Printf("%d: %d x %d - ", i, modes[i].width,modes[i].height);
  284.             if (modes[i].bytesperpixel == 0)
  285.                 Con_Printf("ModeX\n");
  286.             else
  287.                 Con_Printf("%d bpp\n", modes[i].bytesperpixel<<3);
  288.         }
  289. }
  290.  
  291. /*
  292. ================
  293. VID_NumModes
  294. ================
  295. */
  296. int VID_NumModes ()
  297. {
  298.     int i,i1=0;
  299.     
  300.     for (i=0;i<num_modes;i++)
  301.         i1+=(modes[i].width?1:0);
  302.     return (i1);
  303. }
  304.  
  305. void VID_NumModes_f (void)
  306. {
  307.     Con_Printf("%d modes\n",VID_NumModes());
  308. }
  309.  
  310. void VID_Debug_f (void)
  311. {
  312.     Con_Printf("mode: %d\n",current_mode);
  313.     Con_Printf("height x width: %d x %d\n",vid.height,vid.width);
  314.     Con_Printf("bpp: %d\n",modes[current_mode].bytesperpixel*8);
  315.     Con_Printf("vid.aspect: %f\n",vid.aspect);
  316. }
  317.  
  318.  
  319.  
  320. void VID_InitModes(void)
  321. {
  322.  
  323.     int i;
  324.  
  325. // get complete information on all modes
  326.  
  327.     num_modes = vga_lastmodenumber()+1;
  328.     modes = Z_Malloc(num_modes * sizeof(vga_modeinfo));
  329.     for (i=0 ; i<num_modes ; i++)
  330.     {
  331.         if (vga_hasmode(i))
  332.             Q_memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
  333.         else
  334.             modes[i].width = 0; // means not available
  335.     }
  336.  
  337. // filter for modes i don't support
  338.  
  339.     for (i=0 ; i<num_modes ; i++)
  340.     {
  341.         if (modes[i].bytesperpixel != 1 && modes[i].colors != 256) 
  342.             modes[i].width = 0;
  343.     }
  344.  
  345. }
  346.  
  347. int get_mode(char *name, int width, int height, int depth)
  348. {
  349.  
  350.     int i;
  351.     int ok, match;
  352.  
  353.     match = (!!width) + (!!height)*2 + (!!depth)*4;
  354.  
  355.     if (name)
  356.     {
  357.         i = vga_getmodenumber(name);
  358.         if (!modes[i].width)
  359.         {
  360.             Sys_Printf("Mode [%s] not supported\n", name);
  361.             i = G320x200x256;
  362.         }
  363.     }
  364.     else
  365.     {
  366.         for (i=0 ; i<num_modes ; i++)
  367.             if (modes[i].width)
  368.             {
  369.                 ok = (modes[i].width == width)
  370.                     + (modes[i].height == height)*2
  371.                     + (modes[i].bytesperpixel == depth/8)*4;
  372.                 if ((ok & match) == ok)
  373.                     break;
  374.             }
  375.         if (i==num_modes)
  376.         {
  377.             Sys_Printf("Mode %dx%d (%d bits) not supported\n",
  378.                 width, height, depth);
  379.             i = G320x200x256;
  380.         }
  381.     }
  382.  
  383.     return i;
  384.  
  385. }
  386.  
  387. int matchmouse(int mouse, char *name)
  388. {
  389.     int i;
  390.     for (i=0 ; i<num_mice ; i++)
  391.         if (!strcmp(mice[i].name, name))
  392.             return i;
  393.     return mouse;
  394. }
  395.  
  396. #if 0
  397.  
  398. void vtswitch(int newconsole)
  399. {
  400.  
  401.     int fd;
  402.     struct vt_stat x;
  403.  
  404. // switch consoles and wait until reactivated
  405.     fd = open("/dev/console", O_RDONLY);
  406.     ioctl(fd, VT_GETSTATE, &x);
  407.     ioctl(fd, VT_ACTIVATE, newconsole);
  408.     ioctl(fd, VT_WAITACTIVE, x.v_active);
  409.     close(fd);
  410.  
  411. }
  412.  
  413. #endif
  414.  
  415. void keyhandler(int scancode, int state)
  416. {
  417.     
  418.     int sc;
  419.  
  420.     sc = scancode & 0x7f;
  421. //    Con_Printf("scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":"");
  422.     Key_Event(scantokey[sc], state == KEY_EVENTPRESS);
  423.  
  424. }
  425.  
  426. void VID_Shutdown(void)
  427. {
  428.  
  429.     if (!svgalib_inited) return;
  430.  
  431. //    printf("shutdown graphics called\n");
  432.     if (UseKeyboard)
  433.         keyboard_close();
  434.     if (UseDisplay)
  435.         vga_setmode(TEXT);
  436. //    printf("shutdown graphics finished\n");
  437.  
  438.     svgalib_inited = 0;
  439.  
  440. }
  441.  
  442. void VID_ShiftPalette(unsigned char *p)
  443. {
  444.     VID_SetPalette(p);
  445. }
  446.  
  447. void VID_SetPalette(byte *palette)
  448. {
  449.  
  450.     static int tmppal[256*3];
  451.     int *tp;
  452.     int i;
  453.  
  454.     if (!svgalib_inited)
  455.         return;
  456.  
  457.     memcpy(vid_current_palette, palette, sizeof(vid_current_palette));
  458.  
  459.     if (vga_getcolors() == 256)
  460.     {
  461.  
  462.         tp = tmppal;
  463.         for (i=256*3 ; i ; i--)
  464.             *(tp++) = *(palette++) >> 2;
  465.  
  466.         if (UseDisplay && vga_oktowrite())
  467.             vga_setpalvec(0, 256, tmppal);
  468.  
  469.     }
  470. }
  471.  
  472. int VID_SetMode (int modenum, unsigned char *palette)
  473. {
  474.     int bsize, zsize, tsize;
  475.  
  476.     if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width)
  477.     {
  478.         Cvar_SetValue ("vid_mode", (float)current_mode);
  479.         
  480.         Con_Printf("No such video mode: %d\n",modenum);
  481.         
  482.         return 0;
  483.     }
  484.  
  485.     Cvar_SetValue ("vid_mode", (float)modenum);
  486.     
  487.     current_mode=modenum;
  488.  
  489.     vid.width = modes[current_mode].width;
  490.     vid.height = modes[current_mode].height;
  491.  
  492.     VGA_width = modes[current_mode].width;
  493.     VGA_height = modes[current_mode].height;
  494.     VGA_planar = modes[current_mode].bytesperpixel == 0;
  495.     VGA_rowbytes = modes[current_mode].linewidth;
  496.     vid.rowbytes = modes[current_mode].linewidth;
  497.     if (VGA_planar) {
  498.         VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
  499.         vid.rowbytes = modes[current_mode].linewidth*4;
  500.     }
  501.  
  502.     vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
  503.     vid.colormap = (pixel_t *) host_colormap;
  504.     vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
  505.     vid.conrowbytes = vid.rowbytes;
  506.     vid.conwidth = vid.width;
  507.     vid.conheight = vid.height;
  508.     vid.numpages = 1;
  509.     
  510.     vid.maxwarpwidth = WARP_WIDTH;
  511.     vid.maxwarpheight = WARP_HEIGHT;
  512.  
  513.     // alloc zbuffer and surface cache
  514.     if (d_pzbuffer) {
  515.         D_FlushCaches();
  516.         Hunk_FreeToHighMark (VID_highhunkmark);
  517.         d_pzbuffer = NULL;
  518.         vid_surfcache = NULL;
  519.     }
  520.  
  521.     bsize = vid.rowbytes * vid.height;
  522.     tsize = D_SurfaceCacheForRes (vid.width, vid.height);
  523.     zsize = vid.width * vid.height * sizeof(*d_pzbuffer);
  524.  
  525.     VID_highhunkmark = Hunk_HighMark ();
  526.  
  527.     d_pzbuffer = Hunk_HighAllocName (bsize+tsize+zsize, "video");
  528.  
  529.     vid_surfcache = ((byte *)d_pzbuffer) + zsize;
  530.  
  531.     vid.conbuffer = vid.buffer = (pixel_t *)(((byte *)d_pzbuffer) + zsize + tsize);
  532.  
  533.     D_InitCaches (vid_surfcache, tsize);
  534.  
  535. // get goin'
  536.  
  537.     vga_setmode(current_mode);
  538.     VID_SetPalette(palette);
  539.  
  540.     VGA_pagebase = vid.direct = framebuffer_ptr = (char *) vga_getgraphmem();
  541. //        if (vga_setlinearaddressing()>0)
  542. //            framebuffer_ptr = (char *) vga_getgraphmem();
  543.     if (!framebuffer_ptr)
  544.         Sys_Error("This mode isn't hapnin'\n");
  545.  
  546.     vga_setpage(0);
  547.  
  548.     svgalib_inited=1;
  549.  
  550.     vid.recalc_refdef = 1;                // force a surface cache flush
  551.  
  552.     return 0;
  553. }
  554.  
  555. void VID_Init(unsigned char *palette)
  556. {
  557.  
  558.     int i;
  559.     int w, h, d;
  560.  
  561.     if (svgalib_inited)
  562.         return;
  563.  
  564. //    Cmd_AddCommand ("gamma", VID_Gamma_f);
  565.  
  566.     if (UseDisplay)
  567.     {
  568.         vga_init();
  569.  
  570.         VID_InitModes();
  571.  
  572.         Cvar_RegisterVariable (&vid_mode);
  573.         Cvar_RegisterVariable (&vid_redrawfull);
  574.         Cvar_RegisterVariable (&vid_waitforrefresh);
  575.         
  576.         Cmd_AddCommand("vid_nummodes", VID_NumModes_f);
  577.         Cmd_AddCommand("vid_describemode", VID_DescribeMode_f);
  578.         Cmd_AddCommand("vid_describemodes", VID_DescribeModes_f);
  579.         Cmd_AddCommand("vid_debug", VID_Debug_f);
  580.  
  581.     // interpret command-line params
  582.  
  583.         w = h = d = 0;
  584.         if (getenv("GSVGAMODE"))
  585.             current_mode = get_mode(getenv("GSVGAMODE"), w, h, d);
  586.         else if (COM_CheckParm("-mode"))
  587.             current_mode = get_mode(com_argv[COM_CheckParm("-mode")+1], w, h, d);
  588.         else if (COM_CheckParm("-w") || COM_CheckParm("-h")
  589.             || COM_CheckParm("-d"))
  590.         {
  591.             if (COM_CheckParm("-w"))
  592.                 w = Q_atoi(com_argv[COM_CheckParm("-w")+1]);
  593.             if (COM_CheckParm("-h"))
  594.                 h = Q_atoi(com_argv[COM_CheckParm("-h")+1]);
  595.             if (COM_CheckParm("-d"))
  596.                 d = Q_atoi(com_argv[COM_CheckParm("-d")+1]);
  597.             current_mode = get_mode(0, w, h, d);
  598.         }
  599.         else
  600.             current_mode = G320x200x256;
  601.  
  602.     // set vid parameters
  603.         VID_SetMode(current_mode, palette);
  604.  
  605.         VID_SetPalette(palette);
  606.  
  607.         // we do want to run in the background when switched away
  608.         vga_runinbackground(1);    
  609.     }
  610.  
  611.     if (COM_CheckParm("-nokbd")) UseKeyboard = 0;
  612.  
  613.     if (UseKeyboard)
  614.     {
  615.         for (i=0 ; i<128 ; i++)
  616.             scantokey[i] = ' ';
  617.  
  618.         scantokey[42] = K_SHIFT;
  619.         scantokey[54] = K_SHIFT;
  620.         scantokey[72] = K_UPARROW;
  621.         scantokey[103] = K_UPARROW;
  622.         scantokey[80] = K_DOWNARROW;
  623.         scantokey[108] = K_DOWNARROW;
  624.         scantokey[75] = K_LEFTARROW;
  625.         scantokey[105] = K_LEFTARROW;
  626.         scantokey[77] = K_RIGHTARROW;
  627.         scantokey[106] = K_RIGHTARROW;
  628.         scantokey[29] = K_CTRL;
  629.         scantokey[97] = K_CTRL;
  630.         scantokey[56] = K_ALT;
  631.         scantokey[100] = K_ALT;
  632. //        scantokey[58] = JK_CAPS;
  633. //        scantokey[69] = JK_NUM_LOCK;
  634.         scantokey[71] = K_HOME;
  635.         scantokey[73] = K_PGUP;
  636.         scantokey[79] = K_END;
  637.         scantokey[81] = K_PGDN;
  638.         scantokey[82] = K_INS;
  639.         scantokey[83] = K_DEL;
  640.         scantokey[1 ] = K_ESCAPE;
  641.         scantokey[28] = K_ENTER;
  642.         scantokey[15] = K_TAB;
  643.         scantokey[14] = K_BACKSPACE;
  644.         scantokey[119] = K_PAUSE;
  645.         scantokey[57] = ' ';
  646.  
  647.         scantokey[102] = K_HOME;
  648.         scantokey[104] = K_PGUP;
  649.         scantokey[107] = K_END;
  650.         scantokey[109] = K_PGDN;
  651.         scantokey[110] = K_INS;
  652.         scantokey[111] = K_DEL;
  653.  
  654.         scantokey[2] = '1';
  655.         scantokey[3] = '2';
  656.         scantokey[4] = '3';
  657.         scantokey[5] = '4';
  658.         scantokey[6] = '5';
  659.         scantokey[7] = '6';
  660.         scantokey[8] = '7';
  661.         scantokey[9] = '8';
  662.         scantokey[10] = '9';
  663.         scantokey[11] = '0';
  664.         scantokey[12] = '-';
  665.         scantokey[13] = '=';
  666.         scantokey[41] = '`';
  667.         scantokey[26] = '[';
  668.         scantokey[27] = ']';
  669.         scantokey[39] = ';';
  670.         scantokey[40] = '\'';
  671.         scantokey[51] = ',';
  672.         scantokey[52] = '.';
  673.         scantokey[53] = '/';
  674.         scantokey[43] = '\\';
  675.  
  676.         scantokey[59] = K_F1;
  677.         scantokey[60] = K_F2;
  678.         scantokey[61] = K_F3;
  679.         scantokey[62] = K_F4;
  680.         scantokey[63] = K_F5;
  681.         scantokey[64] = K_F6;
  682.         scantokey[65] = K_F7;
  683.         scantokey[66] = K_F8;
  684.         scantokey[67] = K_F9;
  685.         scantokey[68] = K_F10;
  686.         scantokey[87] = K_F11;
  687.         scantokey[88] = K_F12;
  688.         scantokey[30] = 'a';
  689.         scantokey[48] = 'b';
  690.         scantokey[46] = 'c';
  691.         scantokey[32] = 'd';       
  692.         scantokey[18] = 'e';       
  693.         scantokey[33] = 'f';       
  694.         scantokey[34] = 'g';       
  695.         scantokey[35] = 'h';       
  696.         scantokey[23] = 'i';       
  697.         scantokey[36] = 'j';       
  698.         scantokey[37] = 'k';       
  699.         scantokey[38] = 'l';       
  700.         scantokey[50] = 'm';       
  701.         scantokey[49] = 'n';       
  702.         scantokey[24] = 'o';       
  703.         scantokey[25] = 'p';       
  704.         scantokey[16] = 'q';       
  705.         scantokey[19] = 'r';       
  706.         scantokey[31] = 's';       
  707.         scantokey[20] = 't';       
  708.         scantokey[22] = 'u';       
  709.         scantokey[47] = 'v';       
  710.         scantokey[17] = 'w';       
  711.         scantokey[45] = 'x';       
  712.         scantokey[21] = 'y';       
  713.         scantokey[44] = 'z';       
  714.  
  715.         if (keyboard_init())
  716.             Sys_Error("keyboard_init() failed");
  717.         keyboard_seteventhandler(keyhandler);
  718.     }
  719.  
  720. }
  721.  
  722. void VID_Update(vrect_t *rects)
  723. {
  724.     if (!svgalib_inited)
  725.         return;
  726.  
  727.     if (!vga_oktowrite())
  728.         return; // can't update screen if it's not active
  729.  
  730.     if (vid_waitforrefresh.value)
  731.         vga_waitretrace();
  732.  
  733.     if (VGA_planar)
  734.         VGA_UpdatePlanarScreen (vid.buffer);
  735.  
  736.     else if (vid_redrawfull.value) {
  737.         int total = vid.rowbytes * vid.height;
  738.         int offset;
  739.  
  740.         for (offset=0;offset<total;offset+=0x10000) {
  741.             vga_setpage(offset/0x10000);
  742.             memcpy(framebuffer_ptr,
  743.                     vid.buffer + offset,
  744.                     ((total-offset>0x10000)?0x10000:(total-offset)));
  745.         }
  746.     } else {
  747.         int ycount;
  748.         int offset;
  749.         int vidpage=0;
  750.  
  751.         vga_setpage(0);
  752.  
  753.         while (rects)
  754.         {
  755.             ycount = rects->height;
  756.             offset = rects->y * vid.rowbytes + rects->x;
  757.             while (ycount--)
  758.             {
  759.                 register int i = offset % 0x10000;
  760.     
  761.                 if ((offset / 0x10000) != vidpage) {
  762.                     vidpage=offset / 0x10000;
  763.                     vga_setpage(vidpage);
  764.                 }
  765.                 if (rects->width + i > 0x10000) {
  766.                     memcpy(framebuffer_ptr + i, 
  767.                             vid.buffer + offset, 
  768.                             0x10000 - i);
  769.                     vga_setpage(++vidpage);
  770.                     memcpy(framebuffer_ptr,
  771.                             vid.buffer + offset + 0x10000 - i, 
  772.                             rects->width - 0x10000 + i);
  773.                 } else
  774.                     memcpy(framebuffer_ptr + i, 
  775.                             vid.buffer + offset, 
  776.                             rects->width);
  777.                 offset += vid.rowbytes;
  778.             }
  779.     
  780.             rects = rects->pnext;
  781.         }
  782.     }
  783.     
  784.     if (vid_mode.value != current_mode)
  785.         VID_SetMode ((int)vid_mode.value, vid_current_palette);
  786. }
  787.  
  788. static int dither;
  789.  
  790. void VID_DitherOn(void)
  791. {
  792.     if (dither == 0)
  793.     {
  794. //        R_ViewChanged (&vrect, sb_lines, vid.aspect);
  795.         dither = 1;
  796.     }
  797. }
  798.  
  799. void VID_DitherOff(void)
  800. {
  801.     if (dither)
  802.     {
  803. //        R_ViewChanged (&vrect, sb_lines, vid.aspect);
  804.         dither = 0;
  805.     }
  806. }
  807.  
  808. void Sys_SendKeyEvents(void)
  809. {
  810.     if (!svgalib_inited)
  811.         return;
  812.  
  813.     if (UseKeyboard)
  814.         while (keyboard_update());
  815. }
  816.  
  817. void Force_CenterView_f (void)
  818. {
  819.     cl.viewangles[PITCH] = 0;
  820. }
  821.  
  822.  
  823. void mousehandler(int buttonstate, int dx, int dy)
  824. {
  825.     mouse_buttonstate = buttonstate;
  826.     mx += dx;
  827.     my += dy;
  828. }
  829.  
  830. void IN_Init(void)
  831. {
  832.  
  833.     int mtype;
  834.     char *mousedev;
  835.     int mouserate;
  836.  
  837.     if (UseMouse)
  838.     {
  839.  
  840.         Cvar_RegisterVariable (&mouse_button_commands[0]);
  841.         Cvar_RegisterVariable (&mouse_button_commands[1]);
  842.         Cvar_RegisterVariable (&mouse_button_commands[2]);
  843.         Cvar_RegisterVariable (&m_filter);
  844.         Cmd_AddCommand ("force_centerview", Force_CenterView_f);
  845.  
  846.         mouse_buttons = 3;
  847.  
  848.         mtype = vga_getmousetype();
  849.  
  850.         mousedev = "/dev/mouse";
  851.         if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV");
  852.         if (COM_CheckParm("-mdev"))
  853.             mousedev = com_argv[COM_CheckParm("-mdev")+1];
  854.  
  855.         mouserate = 1200;
  856.         if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE"));
  857.         if (COM_CheckParm("-mrate"))
  858.             mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]);
  859.  
  860. //        printf("Mouse: dev=%s,type=%s,speed=%d\n",
  861. //            mousedev, mice[mtype].name, mouserate);
  862.         if (mouse_init(mousedev, mtype, mouserate))
  863.         {
  864.             Con_Printf("No mouse found\n");
  865.             UseMouse = 0;
  866.         }
  867.         else
  868.             mouse_seteventhandler(mousehandler);
  869.  
  870.     }
  871.  
  872. }
  873.  
  874. void IN_Shutdown(void)
  875. {
  876.     if (UseMouse)
  877.         mouse_close();
  878. }
  879.  
  880. /*
  881. ===========
  882. IN_Commands
  883. ===========
  884. */
  885. void IN_Commands (void)
  886. {
  887.     if (UseMouse && cls.state != ca_dedicated)
  888.     {
  889.         // poll mouse values
  890.         while (mouse_update())
  891.             ;
  892.  
  893.         // perform button actions
  894.         if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
  895.             !(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
  896.             Key_Event (K_MOUSE1, true);
  897.         else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
  898.             (mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
  899.             Key_Event (K_MOUSE1, false);
  900.  
  901.         if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
  902.             !(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
  903.             Key_Event (K_MOUSE2, true);
  904.         else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
  905.             (mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
  906.             Key_Event (K_MOUSE2, false);
  907.  
  908.         if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
  909.             !(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
  910.             Key_Event (K_MOUSE3, true);
  911.         else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
  912.             (mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
  913.             Key_Event (K_MOUSE3, false);
  914.  
  915.         mouse_oldbuttonstate = mouse_buttonstate;
  916.     }
  917. }
  918.  
  919. /*
  920. ===========
  921. IN_Move
  922. ===========
  923. */
  924. void IN_MouseMove (usercmd_t *cmd)
  925. {
  926.     if (!UseMouse)
  927.         return;
  928.  
  929.     // poll mouse values
  930.     while (mouse_update())
  931.         ;
  932.  
  933.     if (m_filter.value)
  934.     {
  935.         mouse_x = (mx + old_mouse_x) * 0.5;
  936.         mouse_y = (my + old_mouse_y) * 0.5;
  937.     }
  938.     else
  939.     {
  940.         mouse_x = mx;
  941.         mouse_y = my;
  942.     }
  943.     old_mouse_x = mx;
  944.     old_mouse_y = my;
  945.     mx = my = 0; // clear for next update
  946.  
  947.     mouse_x *= sensitivity.value;
  948.     mouse_y *= sensitivity.value;
  949.  
  950. // add mouse X/Y movement to cmd
  951.     if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
  952.         cmd->sidemove += m_side.value * mouse_x;
  953.     else
  954.         cl.viewangles[YAW] -= m_yaw.value * mouse_x;
  955.     
  956.     if (in_mlook.state & 1)
  957.         V_StopPitchDrift ();
  958.         
  959.     if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
  960.     {
  961.         cl.viewangles[PITCH] += m_pitch.value * mouse_y;
  962.         if (cl.viewangles[PITCH] > 80)
  963.             cl.viewangles[PITCH] = 80;
  964.         if (cl.viewangles[PITCH] < -70)
  965.             cl.viewangles[PITCH] = -70;
  966.     }
  967.     else
  968.     {
  969.         if ((in_strafe.state & 1) && noclip_anglehack)
  970.             cmd->upmove -= m_forward.value * mouse_y;
  971.         else
  972.             cmd->forwardmove -= m_forward.value * mouse_y;
  973.     }
  974. }
  975.  
  976. void IN_Move (usercmd_t *cmd)
  977. {
  978.     IN_MouseMove(cmd);
  979. }
  980.  
  981.  
  982. /*
  983. ================
  984. VID_ModeInfo
  985. ================
  986. */
  987. char *VID_ModeInfo (int modenum)
  988. {
  989.     static char    *badmodestr = "Bad mode number";
  990.     static char modestr[40];
  991.  
  992.     if (modenum == 0)
  993.     {
  994.         sprintf (modestr, "%d x %d, %d bpp",
  995.                  vid.width, vid.height, modes[current_mode].bytesperpixel*8);
  996.         return (modestr);
  997.     }
  998.     else
  999.     {
  1000.         return (badmodestr);
  1001.     }
  1002. }
  1003.  
  1004.